package philbot;



import de.tabacha.cgo.Board;
import de.tabacha.cgo.Constants;
import de.tabacha.cgo.Field;

/*
 * WrapperPosition is my first implementation of the "AbstractPosition" class
 * It wraps the ConwayGo built in "Board" class
 * 
 * This is inefficient in many ways.
 * But works for proof of concept purposes
 * 
 * I have not tested this in a while, so it might have some bad code rot.  
 */
//public class WrapperPosition extends AbstractPosition {
public class WrapperPosition {
	//local state
	private Board b;
	private States state;
	private boolean side;
	
	/**
	 * Basic constructor
	 * @deprecated
	 */
	public WrapperPosition(Board b, States state){
		this.b = (Board) b.clone();
		this.state = state;
		this.side=true;
	}
	
	public WrapperPosition(Board b, States state, boolean side){
		this.b = (Board) b.clone();
		this.state = state;
		this.side=side;
	}
	
	/**
	 * @see philbot.AbstractPosition#getChildren()
	 */
	/*
	@Override
	public List<AbstractPosition> getChildren(){
		List<AbstractPosition> lst = new ArrayList<AbstractPosition>();
		if(this.state == States.START){
			for(AbstractPosition p: this.getJumps()){
				lst.add(p);
			}
			for(AbstractPosition p: this.getPuts()){
				lst.add(p);
			}
		}else if(this.state == States.JUMP){
			for(AbstractPosition p: this.getJumps()){
				lst.add(p);
			}
			lst.add(new WrapperPosition(this.b,States.START,!side));
		}else{
			lst.add(new WrapperPosition(this.b,States.JUMP,!side));
		}
		return lst;
	}*/
	/*
	private Collection<AbstractPosition> getJumps() {
		List<AbstractPosition> lst = new LinkedList<AbstractPosition>();
		for(byte i = 0; i < 8; i++){
			Board trial = (Board) b.clone();
			byte[] direc = new byte[1];
			direc[0] = i;
			try {
				trial.move(new Jump(direc));
				lst.add(new WrapperPosition(trial, States.NULLMOVE, !side));
			} catch (InvalidMoveException e) {
				// TODO Auto-generated catch block
				//do nothing
			}
			
		}
		return lst;
	}*/

	/*private Collection<AbstractPosition> getPuts() {
		List<AbstractPosition> lst = new LinkedList<AbstractPosition>();
		for(int i = 0; i< 19;i++){
			for(int j = 0; j< 19; j++){
				if(b.on(i, j) == Constants.EMPTY){
					Field f = new Field(i,j);
					Put p = new Put(f);
					Board temp = (Board) b.clone();
					try {
						temp.move(p);
						lst.add(new WrapperPosition(temp,States.START, !side));
					} catch (InvalidMoveException e) {
						//do nothing
					}
				}
			}
		}
		return lst;
	}*/

	/**
	 * @see philbot.AbstractPosition#eval(boolean)
	 * @deprecated
	 */
	//@Override
	public int eval(boolean ignore) {
		// TODO A better eval
		// This should probably take into account position type
		if((state != States.NULLMOVE) ^ side){
			return b.getBall().row();
		}else{
			return -b.getBall().row();
		}
	}
	/**
	 * 	 
	 * @see philbot.AbstractPosition#eval()
	 */
	//@Override
	public int eval(){
		return this.eval(true);
	}
	//@Override 
	public int eval(Evaluator e){
		return this.eval();
	}
	/**
	 * @see java.lang.Object#toString()
	 */
	//@Override 
	public String toString(){
		StringBuilder build = new StringBuilder();
		build.append(state.toString());
		build.append("\n");
		for(int i = 0; i < 19; i++){
			for(int j = 0; j<19; j++){
				byte type = this.b.on(new Field(j,i));
				if(type == Constants.BALL)
					build.append("X");
				else if(type == Constants.PIECE)
					build.append("O");
				else
					build.append(" ");
				build.append(",");
			}
			build.append("\n");
		}
		return build.toString();
	}

	//@Override
	public boolean isVictory() {
		return this.b.getBall().isInGoal();
	}
	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override 
	public boolean equals(Object o){
		if(o instanceof WrapperPosition){
			WrapperPosition w = (WrapperPosition) o;
			if(this.side != w.side)
				return false;
			if(this.state != w.state)
				return false;
			for(int i = 0; i < 19; i++){
				for(int j = 0; j<19; j++){
					Field f = new Field(i,j);
					if(this.b.on(f) != w.b.on(f))
						return false;
				}
			}
			return true;
		}else{
			return false;
		}
	}
	/*
	 * Really slow
	 * totally naive implementation
	 * @see java.lang.Object#hashCode()
	 */
	@Override 
	public int hashCode(){
		int goo = 0;
		for(int i = 0; i < 19; i++){
			for(int j = 0; j<19; j++){
				Field f = new Field(i,j);
				goo += this.b.on(f);
			}
		}
		goo += this.state.hashCode();
		goo = (this.side) ? goo*(-1) : goo;
		return goo;
	}
	//@Override 
	public int whoVictory(){
		return 0;
	}

}
